﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.Data.SqlServerCe;
using System.Collections;
using System.Collections.ObjectModel;

namespace QuizEngine.Data
{
    public class DbSet<T> : IEnumerable<T>
    {
        protected Collection<T> _innerCollection;
        Type _type;
        List<PropertyInfo> _properties;
        PropertyInfo _keyProperty;
        Type _keyPropertyType;

        string _connectString = ConfigurationManager.ConnectionStrings["QuizEngine.Properties.Settings.QuizEngineConnectionString"].ConnectionString;

        public DbSet()
        {
            _type = typeof(T);
            var properties = _type.GetProperties();
            _keyProperty = _type.GetProperty(_type.Name + "Id");
            _keyPropertyType = _keyProperty.PropertyType;
            _properties = new List<PropertyInfo>();
            foreach (PropertyInfo property in properties)
            {
                if (property.PropertyType == typeof(Int32)
                    || property.PropertyType == typeof(String)
                    || property.PropertyType == typeof(Byte)
                    || property.PropertyType == typeof(Int16)
                    || property.PropertyType == typeof(DateTime)
                    || property.PropertyType == typeof(Char)
                    || property.PropertyType == typeof(Boolean)
                    || property.PropertyType == typeof(Double))
                {
                    _properties.Add(property);
                }
            }
        }


        public T Find(object keyValue)
        {
            var obj = Activator.CreateInstance(typeof(T));
            if (_properties.Count > 0)
            {
                string columnList = "";
                int count = 0;
                foreach (PropertyInfo property in _properties)
                {
                    count++;
                    if (count < _properties.Count)
                    {
                        columnList += (" [" + property.Name + "],");
                    }
                    else
                    {
                        columnList += (" [" + property.Name + "] ");
                    }
                }
                try
                {
                    SqlCeConnection sqlCnn = new SqlCeConnection(_connectString);
                    SqlCeCommand sqlCmd = new SqlCeCommand();
                    sqlCmd.Connection = sqlCnn;
                    sqlCmd.CommandType = CommandType.Text;
                    sqlCmd.CommandText = "SELECT" + columnList + "FROM " + _type.Name
                        + " WHERE " + (_keyProperty.Name) + " = " + "@key";
                    SqlDbType sqlDataType = SqlDbType.Int;
                    if (_keyPropertyType == typeof(Int32)) sqlDataType = SqlDbType.Int;
                    //else if (_keyPropertyType == typeof(String)) sqlDataType = SqlDbType.NVarChar;
                    //else if (_keyPropertyType == typeof(Byte)) sqlDataType = SqlDbType.TinyInt;
                    SqlCeParameter sqlPara = sqlCmd.Parameters.Add("@key", Enum.Parse(typeof(SqlDbType), _keyProperty.GetCustomAttributes(typeof(DbTypeAttribute), true).GetValue(0).ToString()));
                    sqlPara.Value = keyValue;
                    sqlPara.Direction = ParameterDirection.Input;
                    sqlCnn.Open();
                    SqlCeDataReader sqlDataReader = sqlCmd.ExecuteReader();
                    while (sqlDataReader.Read())
                    {
                        foreach (PropertyInfo property in _properties)
                        {
                            property.SetValue(obj, sqlDataReader[property.Name], null);
                        }
                    }
                    sqlCnn.Close();
                    return (T)obj;
                }
                catch(Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message + "\n"
                        + ex.StackTrace);
                    
                    throw;
                }
            }
            else return default(T);
        }

        public List<T> Include(string name)
        {
            return new List<T>();
        }

        public List<T> Where(Predicate<T> values)
        {
            List<T> dataList = new List<T>();
            return dataList.FindAll(values);
        }

        private List<T> getData()
        {
            List<T> dataList = new List<T>();
            var obj = Activator.CreateInstance(typeof(T));
            if (_properties.Count > 0)
            {
                string columnList = "";
                int count = 0;
                foreach (PropertyInfo property in _properties)
                {
                    count++;
                    if (count < _properties.Count)
                    {
                        columnList += (" [" + property.Name + "],");
                    }
                    else
                    {
                        columnList += (" [" + property.Name + "] ");
                    }
                }
                try
                {
                    SqlCeConnection sqlCnn = new SqlCeConnection(_connectString);
                    SqlCeCommand sqlCmd = new SqlCeCommand();
                    sqlCmd.Connection = sqlCnn;
                    sqlCmd.CommandType = CommandType.Text;
                    sqlCmd.CommandText = "SELECT" + columnList + "FROM " + _type.Name;
                    sqlCnn.Open();
                    SqlCeDataReader sqlDataReader = sqlCmd.ExecuteReader();
                    while (sqlDataReader.Read())
                    {
                        foreach (PropertyInfo property in _properties)
                        { 
                            property.SetValue(obj, sqlDataReader[property.Name], null);
                        }
                    }
                    sqlCnn.Close();
                    sqlDataReader.Dispose();
                    return dataList;
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message + "\n"
                        + ex.StackTrace);

                    throw;
                }
            }
            return dataList;
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _innerCollection.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _innerCollection.GetEnumerator();
        }
    }
}
